Skip to content

feat(plugin): add Microsoft Foundry as a built-in auth provider#28073

Open
pandma wants to merge 2 commits into
anomalyco:devfrom
pandma:feat/foundry-provider
Open

feat(plugin): add Microsoft Foundry as a built-in auth provider#28073
pandma wants to merge 2 commits into
anomalyco:devfrom
pandma:feat/foundry-provider

Conversation

@pandma
Copy link
Copy Markdown

@pandma pandma commented May 17, 2026

Issue for this PR

Closes #14879

Type of change

  • New feature
  • Bug fix
  • Refactor / code improvement
  • Documentation

What does this PR do?

It adds Microsoft Foundry as a provider option in /login and a small chat.params hook so Foundry gpt-5.x deployments don't fail on every request.

A note on the CONTRIBUTING rule "new providers should go to models.dev first": Foundry doesn't fit that model. A Foundry "provider" is a user's own Azure resource + project + deployments. There's no fixed model list to put in the catalog — every user has different deployment names. So the catalog can't represent it; the right place is a plugin.

Two things were needed:

  1. The /login flow asks the user for their resource hostname, project name and the deployment names they have. The credential is saved under the foundry provider id and the user then references it from their own opencode.json (the JSDoc in foundry.ts has the minimal shape).

  2. Foundry's OpenAI-compatible endpoint on gpt-5.x returns 400 for reasoningSummary, reasoningEffort, textVerbosity, and won't accept max_tokens (wants max_completion_tokens instead). The openai-compatible SDK emits all of those. So when model.providerID === "foundry" the hook strips them from output.options and clears maxOutputTokens. Other providers aren't touched.

How did you verify your code works?

Tested against a real Foundry project end to end:

  1. bun run typecheck — clean (also caught a missing client.auth.get I had to remove before re-running)
  2. bun run dev — boots and logs name=FoundryAuthPlugin loading internal plugin
  3. bun run dev auth list — shows registered providers
  4. Wrote a minimal opencode.json pointing at https://<resource>.services.ai.azure.com/api/projects/<project>/openai/v1 with one model gpt-5.5, then ran:
    bun run dev run -m foundry/gpt-5.5 "Say pong"
    
    → returned pong. Before the hook this errored with Unknown parameter: 'reasoningSummary'.

Curl probes (before writing the hook, to confirm what Foundry actually rejects):

Param the openai-compatible SDK emits Foundry response
reasoningSummary / reasoningEffort / textVerbosity 400 Unknown parameter
max_tokens 400 use 'max_completion_tokens'
temperature: 0.5 400 Only the default (1) value is supported

Screenshots / recordings

No UI change. The only user-visible surface is the /login flow — three text prompts in the same style as the existing Azure plugin (resource hostname, project name, deployments comma-separated).

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Notes

This lands the OpenAI-compatible path on Foundry, which is the common case (gpt-4o-mini, gpt-5.5, etc.). The original reporter on #14879 was hitting /anthropic/v1/messages on Foundry — Claude on Foundry uses a different SDK (@ai-sdk/anthropic) and URL pattern. Happy to do that as a follow-up if this lands.

Foundry deployments live behind project-scoped URLs of the form
  https://<resource>.services.ai.azure.com/api/projects/<project>/openai/v1
and accept either `Authorization: Bearer <key>` or `api-key: <key>`. They are
not present in the models.dev catalog because deployments are user-defined.

This change adds a FoundryAuthPlugin that:

  * Surfaces "foundry" as a selectable provider in `/login`, prompting for
    resource hostname, project name and a comma-separated list of deployment
    names. The credential is stored under the `foundry` provider id; the user
    then references it from their own `opencode.json` provider entry (the
    JSDoc shows the minimal config).

  * Adds a `chat.params` hook that, when the active model's providerID is
    `foundry`, strips `reasoningEffort`, `reasoningSummary`, `textVerbosity`,
    `include` and `promptCacheKey`, and clears `maxOutputTokens`. Foundry's
    OpenAI-compatible endpoint rejects those params for gpt-5.x deployments
    (and the openai-compatible SDK emits `max_tokens` instead of the required
    `max_completion_tokens`, with no rename hook available).

Tested end-to-end against a real Foundry project (gpt-5.5 deployment): the
provider loads, `/login` shows the new flow, and a chat completes with the
hook silently dropping the unsupported params.

Refs: anomalyco#14879
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label May 17, 2026
@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label May 17, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Azure Foundry for opencode

1 participant